#include "SceneService.h"
#include "../db/DBPoll.h"
#include "../util/DateTime.h"
#include "../util/TextUtil.h"

// 数据表名称
#define SQL_DB_NAME_SCENE	"t_analysis"

// 建表语句
#define SQL_CREATE_SCENE \
"CREATE TABLE IF NOT EXISTS `t_analysis` ("\
"`id` VARCHAR(64) NOT NULL comment '分析编码',"\
"`deviceId` VARCHAR(64) NOT NULL comment '设备编码',"\
"`detectType` TEXT comment '分析类型',"\
"`threshold` int default 70 comment '最小置信度(0-100)',"\
"`model` VARCHAR(64) default NULL comment '分析模型编码',"\
"`alarmInfo` VARCHAR(32) default '' comment '报警描述',"\
"`alarmCode` VARCHAR(32) default '' comment '报警代码(第三方识别)',"\
"`createTime` DATETIME default NULL comment '添加时间',"\
"`updateTime` DATETIME default NULL comment '更新时间',"\
"`reserver1` VARCHAR(255) default NULL comment '保留字段1',"\
"`reserver2` VARCHAR(255) default NULL comment '保留字段2',"\
"primary key(`id`),"\
"FOREIGN KEY (`deviceId`) REFERENCES t_device(`id`) ON DELETE CASCADE ON UPDATE CASCADE"\
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分析模型'"

// SQLite建表
#define SQL_CREATE_SCENE2	\
"CREATE TABLE IF NOT EXISTS `t_analysis` ("\
"`id` VARCHAR(64) NOT NULL,"\
"`deviceId` VARCHAR(64) NOT NULL,"\
"`detectType` TEXT,"\
"`threshold` int default 70,"\
"`model` VARCHAR(64) default NULL,"\
"`alarmInfo` VARCHAR(32) default '',"\
"`alarmCode` VARCHAR(32) default '',"\
"`createTime` DATETIME default NULL,"\
"`updateTime` DATETIME default NULL,"\
"`reserver1` VARCHAR(255) default NULL,"\
"`reserver2` VARCHAR(255) default NULL,"\
"primary key(`id`),"\
"FOREIGN KEY (`deviceId`) REFERENCES t_device(`id`) ON DELETE CASCADE ON UPDATE CASCADE"\
")"

// 新增语句
#define SQL_INSERT_SCENE \
"insert into t_analysis(`id`, `deviceId`, `detectType`,"\
"`threshold`, `model`, `alarmInfo`, `alarmCode`, `createTime`, `updateTime`)"\
"values('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s')"

// 删除语句					  
#define SQL_DELETE_SCENE \
"delete from t_analysis where `id`='%s'"

// 查询语句					  
#define SQL_QUERY_SCENE \
"select * from t_analysis where `id`='%s'"

// 查询数量		  
#define SQL_QUERY_SCENE_COUNT \
"select count(*) from t_analysis where 1=1"

// 分页查询					  
#define SQL_QUERY_SCENE_PAGE \
"select * from t_analysis where 1=1"

// 设备查询					  
#define SQL_QUERY_DEV_SCENE \
"select * from t_analysis where `deviceId`='%s'"

// 更新语句					  
#define SQL_UPDATE_SCENE \
"update t_analysis set `deviceId`='%s',`detectType`='%s',"\
"`threshold`=%d,`model`='%s',`alarmInfo`='%s',`alarmCode`='%s',"\
"`updateTime`='%s' where `id`='%s'"


SceneService::SceneService()
{
}

SceneService::~SceneService()
{
}

bool SceneService::Exist()
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		bool ret = db->IsTableExist(SQL_DB_NAME_SCENE);
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::Create()
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = db->GetDbType() == 0 ? SQL_CREATE_SCENE : SQL_CREATE_SCENE2;
		sql = TextUtil::get_mutable_instance().Ascii2Utf8(sql.c_str());
		bool ret = db->CreateTable(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::Add(SceneInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_INSERT_SCENE)
			% item.GetId() % item.GetDevice()
			% item.GetDetectType() % item.GetThreshold()
			% item.GetModel() % item.GetAlarmInfo()
			% item.GetAlarmCode()
			% item.GetCreateTime().ToNormalString()
			% item.GetUpdateTime().ToNormalString()
		);

		uint64_t id = db->Insert(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		if (0xffffffff == id)
		{
			return false;
		}
		return true;
	}
	return false;
}

bool SceneService::Delete(SceneInfo& item, bool delFromDB)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		bool ret = false;
		if (delFromDB)
		{
			std::string sql = boost::str(boost::format(SQL_DELETE_SCENE) % item.GetId());
			ret = db->Delete(sql.c_str());
		}

		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

// 查询数量
int SceneService::Count()
{
	int count = 0;
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_SCENE_COUNT));
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			if (db->FetchNextRow())
			{
				char* v = db->GetColValue(0);
				count = std::stoi(v);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
	}
	return count;
}

int SceneService::Count(std::string device)
{
	int count = 0;
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_SCENE_COUNT));
		if (!device.empty())
		{
			sql += boost::str(boost::format(" and `deviceId`= '%s'") % device);
		}
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			if (db->FetchNextRow())
			{
				char* v = db->GetColValue(0);
				count = std::stoi(v);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
	}
	return count;
}

// 查找记录
bool SceneService::FindPage(int pageIndex, int pageSize, std::vector<SceneInfo>& list)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_SCENE_PAGE));
		sql += boost::str(boost::format(" limit %d, %d") % pageIndex % pageSize);
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			while (db->FetchNextRow())
			{
				SceneInfo item;
				ToRecord(db, item);
				list.push_back(item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::FindPage(int pageIndex, int pageSize, std::string device, std::vector<SceneInfo>& list)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_SCENE_PAGE));
		if (!device.empty())
		{
			sql += boost::str(boost::format(" and `deviceId`= '%s'") % device);
		}
		sql += boost::str(boost::format(" limit %d, %d") % pageIndex % pageSize);
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			while (db->FetchNextRow())
			{
				SceneInfo item;
				ToRecord(db, item);
				list.push_back(item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::FindByDevice(std::string device, std::vector<SceneInfo>& list)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_DEV_SCENE) % device);
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			while (db->FetchNextRow())
			{
				SceneInfo item;
				ToRecord(db, item);
				list.push_back(item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::Find(SceneInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_QUERY_SCENE) % item.GetId());
		bool ret = db->Query(sql.c_str());
		if (ret)
		{
			if (db->FetchNextRow())
			{
				ToRecord(db, item);
			}
			db->FreeQueryResult();
		}
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}

bool SceneService::Update(SceneInfo& item)
{
	IDbBasePtr db = DBPoll::get_mutable_instance().Pop();
	if (db)
	{
		std::string sql = boost::str(boost::format(SQL_UPDATE_SCENE)
			% item.GetDevice() % item.GetDetectType()
			% item.GetThreshold() % item.GetModel()
			% item.GetAlarmInfo() % item.GetAlarmCode()
			% item.GetUpdateTime().ToNormalString()
			% item.GetId());
		bool ret = db->Update(sql.c_str());
		DBPoll::get_mutable_instance().Push(db);
		return ret;
	}
	return false;
}


void SceneService::ToRecord(IDbBasePtr db, SceneInfo& item)
{
	std::string id = "";
	if (db->GetColValue(0))
	{
		id = db->GetColValue(0);
	}
	std::string deviceId = "";
	if (db->GetColValue(1))
	{
		deviceId = db->GetColValue(1);
	}
	std::string detectType = "";
	if (db->GetColValue(2))
	{
		detectType = db->GetColValue(2);
	}
	int threshold = 80;
	if (db->GetColValue(3))
	{
		threshold = atoi(db->GetColValue(3));
	}
	std::string model = "";
	if (db->GetColValue(4))
	{
		model = db->GetColValue(4);
	}
	std::string alarmInfo = "";
	if (db->GetColValue(5))
	{
		alarmInfo = db->GetColValue(5);
	}
	std::string alarmCode = "";
	if (db->GetColValue(6))
	{
		alarmCode = db->GetColValue(6);
	}
	std::string createTime = "";
	if (db->GetColValue(7))
	{
		createTime = db->GetColValue(7);
	}
	std::string updateTime = "";
	if (db->GetColValue(8))
	{
		updateTime = db->GetColValue(8);
	}

	item.SetId(id);
	item.SetDevice(deviceId);
	item.SetDetectType(detectType);
	item.SetThreshold(threshold);
	item.SetModel(model);
	item.SetAlarmInfo(alarmInfo);
	item.SetAlarmCode(alarmCode);

	DateTime create_time;
	create_time.From(createTime);
	item.SetCreateTime(create_time);

	DateTime update_time;
	update_time.From(updateTime);
	item.SetUpdateTime(update_time);
}
